package fortunata.jspwikiplugins.vpoet;

import com.ecyrd.jspwiki.plugin.WikiPlugin;
import com.ecyrd.jspwiki.plugin.PluginException;
import com.ecyrd.jspwiki.WikiContext;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.ontology.Individual;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.query.*;
import com.hp.hpl.jena.datatypes.xsd.XSDDateTime;
import org.apache.log4j.Logger;

import java.util.Map;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Calendar;

import fortunata.util.NiceDate;
import fortunata.FortunataPlugin;
import fortunata.fswapps.omemo.Omemo;
import fortunata.fswapps.vpoet.Vpoet;


/**
 * This plugin creates an ordenable wiki list (table) with most information stored in VPOET
 * Information comes from ontologic (OWL) files.
 */
public class TableOfDesignsForVP extends FortunataPlugin implements WikiPlugin {
    private static Logger log = Logger.getLogger( TableOfDesignsForVP.class );
    private Vpoet vpoet;

    public String execute (WikiContext context, Map parameterMap) throws PluginException {
        vpoet = new Vpoet();
        String designerID  = FormManager.getFieldNoEmplyValue("designerID", parameterMap, "designer ID");
        //Creates an empty model
        OntModel m = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM_RDFS_INF, null);
        //Reads Ontology
        vpoet.readSWAppModel(m, context);
        
        StringBuffer sb = new StringBuffer();
        String URI = vpoet.getURI();
        sb.append("%%sortable" + nl);
        sb.append("||DesignID||Elem||Type||Date||Operation" +  nl);
        Property propDesignID = m.getProperty(URI + Vpoet.propNameDesignID);

        Property propOntoElemID = m.getProperty(URI + Vpoet.propNameOntoElemID);
        Property propDesignType = m.getProperty(URI + Vpoet.propNameDesignType);
        Property propModificationDate = m.getProperty(URI + Vpoet.propNameModificationDate);
        ArrayList designsURIs = queryModelForDesignerDesigns (m, designerID);
        Iterator iter = designsURIs.iterator();
        final String pageName = Vpoet.createWikiPageName;  //This "origin" page name is hard-coded TODO
        ArrayList traslationTable = new ArrayList();
        TableOfDesignsForVP.TranslatePair tp = null;

        while (iter.hasNext()){
            Individual indiv = (Individual) m.getIndividual((String)iter.next());
            tp = new TableOfDesignsForVP.TranslatePair("?page=" + pageName,
                                   "?page=" + pageName + "&" +Vpoet.HttpRequestParameter_EditElement + "=" +
                                           indiv.getLocalName());
            traslationTable.add(tp);
            tp = new TableOfDesignsForVP.TranslatePair("?page=" + pageName,
                                   "?page=" + Vpoet.VisualizeWikiPageName + "&" +Vpoet.HttpRequestParameter_VisualizeElement + "=" +
                                           indiv.getLocalName());
                                   //"Wiki.jsp?page=" + pageName,
                                   //"servlet/VPoetRequestServlet?action=renderInput&object=" +
                                   //        indiv.getPropertyValue(propOntoElemID).toString() + "&provider=" +
                                   //        indiv.getPropertyValue(propProviderID).toString() +
                                   //        "&outformat=HTML");
            traslationTable.add(tp);

            sb.append("|" + indiv.getPropertyValue(propDesignID)).toString(); //This recovers the ID
            sb.append("|[" + indiv.getPropertyValue(propOntoElemID).toString() + "|" +
                            Omemo.generatedOntoWikiPagesPrefix +
                                     indiv.getPropertyValue(propOntoElemID).toString() + "]"
                      );
            sb.append("|" + indiv.getPropertyValue(propDesignType).toString());
            sb.append("|" + toNiceDate(indiv.getPropertyValue(propModificationDate)));
            sb.append("| [Edit|" + pageName + "]    [Visualize|" + pageName + "]");
            sb.append(wnl);
        }
//        sb.append("[{FormInput type='hidden' name='numItems' value='" + i+ "'}] \n");
//        sb.append(
//        "%%(text-align:center) \n" +
//                "[{FormInput type='submit' name='doEdit' value='Edit Selected Item'}] \n" +
//                "%%"
//        );
        sb.append("%%");

        //String originalWikiText = sb.toString();
        //String originalHtmlText = renderWikiText(context, originalWikiText);
        return translateToLinkWithParameter(renderWikiText(context, sb.toString()),
                                            traslationTable);

    }

    private static String translateToLinkWithParameter (String htmlText, ArrayList tt){
        //System.out.println(htmlText);
        /*final String  searchForString = "page="+ dummy;    //take care of "?". It is a special character in regex
        Pattern pattern = Pattern.compile( searchForString );
        Matcher matcher = pattern.matcher( htmlText );
        StringBuffer result = new StringBuffer();
        String finalString = "page=" + Vpoet.createWikiPageName + "&" + Vpoet.HttpRequestAttribute_EditElement + "=";
        while( matcher.find() ){
          matcher.appendReplacement( result, finalString );
          System.out.println(result.toString());
        }
        matcher.appendTail( result );
        System.out.println(result.toString());*/
        //System.out.println("poraqui6:" + htmlText);
        String remaining = new String (htmlText);
        StringBuffer result = new StringBuffer();
        TableOfDesignsForVP.TranslatePair tp = null;
        int init, end;
        for (int i = 0 ; i < tt.size(); i++) {
           tp = (TableOfDesignsForVP.TranslatePair)tt.get(i);
           init = remaining.indexOf(tp.getFrom());
           result.append(remaining.substring(0, init));
           result.append(tp.getTo());
           remaining = remaining.substring(init + tp.getFrom().length());
        }
        //System.out.println(result.toString());
        result.append(remaining);
        return result.toString();
    }

    public static void main(String[] args){

        String test1 = "<a class=\"wikipage\" href=\"/JSPWiki2453/Wiki.jsp?page=VPOETCreateViz\">Edit</a> ";
        System.out.println(test1);
        ArrayList traslationTable = new ArrayList();
        TableOfDesignsForVP.TranslatePair tt1 = new TableOfDesignsForVP.TranslatePair("?page=VPOETCreateViz",
                                               "?page=VPOETCreateViz&lirili=xx");
        //TranslatePair tt2 = new TranslatePair (pageName, "&lirili=xx");
        traslationTable.add(tt1);
        //traslationTable.add(tt2);
        System.out.println(translateToLinkWithParameter(test1, traslationTable));
    }

    public static class TranslatePair {
        private String from, to;
        TranslatePair(String from, String to){
            this.from = from;
            this.to = to;
        }
        public String getFrom(){return from;};
        public String getTo(){return to;};
    }

    /**
     *
     * @param m
     * @param providerID
     * @return A list of URIs (String). This list can be empty
     */
    public ArrayList queryModelForDesignerDesigns(OntModel m, String providerID){
         String queryString = "PREFIX vpoet: <" + vpoet.getURI() + "> \n" +
                               "SELECT ?design \n" +
                               "WHERE \n" +
                               " { ?design vpoet:" + Vpoet.propNameProviderID  +  " \"" + providerID   +  "\" . \n" +
                               "   ?design vpoet:" + Vpoet.propNameModificationDate + " ?date " + " . \n" +
                               " }\n" +
                               " ORDER BY DESC(?date)";
          Query query = QueryFactory.create(queryString) ;
          QueryExecution qexec = QueryExecutionFactory.create(query, m) ;
          ArrayList res = new ArrayList();
          try {
            ResultSet results = qexec.execSelect() ;
            for ( ; results.hasNext() ; ){
              QuerySolution sol = results.nextSolution() ;
              res.add(sol.get("design").toString());
            }
          } finally {
             qexec.close() ;
          }
          return res;
    }
    static String toNiceDate(RDFNode n){
          Literal l =  (Literal)(n.as(Literal.class)); //An RDFNode can be a Resource or a Literal
          Calendar c = ((XSDDateTime) l.getValue()).asCalendar();    //asCalendar returns a Calendar but indeed it is a GregorianCalendar
          return NiceDate.niceDateIntervalTillNow(c.getTime());
    }
}
